home *** CD-ROM | disk | FTP | other *** search
- /*
- ** PPCRun
- **
- ** Run an ELF object under AmigaOS as a new PowerPC task.
- **
- ** V0.9a 24-Dec-97 vb
- ** Modified to use inline library calls
- ** V0.9 23-Dec-97 phx
- ** To be compatible with elfrun and SAS/C-ppc, pass the command
- ** line in GPR3, instead argc/argv in GPR3/4.
- ** PPCRun is compiled with vbcc's minimal startup code to get
- ** direct access to the command line.
- ** Removed all debugging output.
- ** Successfully tested with ppc.library V45.2. Removing a crashed
- ** task with CTRL-D works perfectly now. But I'm not sure, if I
- ** fixed a bug or
- ** V0.4 18-Oct-97 phx
- ** Close(errfh) was missing. Included a help text.
- ** V0.3 11-Oct-97 phx
- ** Define DEBUG for debugging output.
- ** V0.2 07-Oct-97 phx
- ** fixed some infinite loops :)
- ** V0.1 04-Oct-97 phx
- ** created
- */
-
- #include <stdio.h>
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <exec/libraries.h>
- #include <exec/ports.h>
- #include <dos/dos.h>
- #include <dos/dosextens.h>
- #include <utility/tagitem.h>
- #include <ppclib/tasks.h>
- #include <ppclib/message.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/ppc.h>
- /*
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <powerup/clib/ppc_protos.h>
- */
- #define VERSION "PPCRun 0.9a (24.12.97)"
- #define PPCLIBVER 44
- #define PPCDEFPRI 0
-
- #define MSGID_EXIT 0x44584954
-
-
- struct StartupData {
- APTR M68kPort; /* the PowerPC task can send messages to this port */
- BPTR std_in; /* standard input handle */
- BPTR std_out; /* standard output handle */
- BPTR std_err; /* standard error handle */
- LONG retCode; /* here we will find the return code from the PPC task */
- ULONG flags; /* additional flags (currently unused) */
- };
-
-
- extern struct ExecBase *SysBase;
-
- struct DOSBase *DOSBase = NULL;
- struct Library *PPCLibBase = NULL;
-
- static const char *ppcrun = "PPCRun";
- static const char *version = "$VER: " VERSION "\r\n";
- static const char *ppclibname = "ppc.library";
-
-
-
- static char *nextarg(char *p)
- /* get pointer to next argument in command line */
- {
- while (*p<=' ' && *p!=0)
- p++;
- if (*p == 0)
- return (NULL);
- return (p);
- }
-
-
- static char *skiparg(char *p)
- /* find end of argument */
- {
- char c;
-
- if (*p != '\"') {
- while (*p > ' ')
- p++;
- }
- else {
- p++;
- do
- c = *p++;
- while (c!='\"' && c!=0);
- if (c==0)
- p--;
- }
- return (p);
- }
-
-
- int main(char *cmdline)
- {
- APTR elfobject,startupmsg,ppctask,ppcmsg;
- BPTR errfh=0;
- char *taskname=NULL,*args=NULL;
- struct MsgPort *m68kport; /* not documented as real MsgPort, but I hope.. */
- int rc = 10;
- struct StartupData *sd; /* data delivered with startup message */
- char c,*elfname,*p;
- ULONG argsize,sigmask=0;
- ULONG sigppc; /* signal mask: PPC message coming in */
- struct Process *pr;
-
- static struct TagItem porttags[] = {
- TAG_END
- };
- static struct TagItem tasktags[] = {
- PPCTASKTAG_NAME,0,
- PPCTASKTAG_ARG1,0,
- PPCTASKTAG_MSGPORT,TRUE,
- PPCTASKTAG_STARTUP_MSG,0,
- PPCTASKTAG_STARTUP_MSGDATA,0,
- PPCTASKTAG_STARTUP_MSGLENGTH,0,
- PPCTASKTAG_STARTUP_MSGID,0,
- PPCTASKTAG_STACKSIZE,0,
- PPCTASKTAG_PRIORITY,PPCDEFPRI,
- TAG_END
- };
-
-
- if (SysBase->LibNode.lib_Version < 36) /* We need OS2.0! */
- exit (15);
- if (!(DOSBase = (struct DOSBase *)OpenLibrary("dos.library",36)))
- exit (15);
-
- if (*cmdline==0 || *cmdline=='?') {
- Printf(VERSION "\n(c)1997 by Frank Wille\n\nUsage: "
- "%s <ELF object> [<aguments> ...]\n",ppcrun);
- rc = 5;
- }
-
- else {
- if (PPCLibBase = OpenLibrary((STRPTR)ppclibname,PPCLIBVER)) {
- if (sd = (struct StartupData *)
- PPCAllocVec(sizeof(struct StartupData),MEMF_CLEAR|MEMF_PUBLIC)) {
- sd->std_in = Input();
- sd->std_out = Output();
- if (errfh = Open("CONSOLE:",MODE_NEWFILE))
- sd->std_err = errfh;
- else
- sd->std_err = sd->std_out;
-
- /* parse options and determine name of ELF object */
- while (cmdline = nextarg(cmdline)) {
- if (*cmdline != '-')
- break;
- cmdline++;
- switch (*cmdline++) {
- /* here we could check for options - currently unused... */
- default:
- Printf("%s: Unrecognized option -%lc!\n",
- ppcrun,(ULONG)*(--cmdline));
- cmdline = skiparg(cmdline);
- break;
- }
- }
- if (cmdline) {
- elfname = cmdline;
- p = skiparg(cmdline);
- c = *p;
- if (*elfname == '\"') { /* file name in quotes? */
- elfname++;
- if (*(p-1) == '\"') {
- c = '\"';
- p--;
- }
- }
- *p = 0;
-
- if (elfobject = PPCLoadObject(elfname)) {
- /* copy command line for PPC task */
- argsize = (p - elfname) + 1;
- if (taskname = (char *)AllocVec(argsize,MEMF_ANY))
- CopyMem(elfname,taskname,argsize);
- *p = c;
- p = cmdline;
- argsize = 0;
- do
- argsize++;
- while (*p++);
- if (args = (char *)PPCAllocVec(argsize,MEMF_ANY))
- CopyMem(cmdline,args,argsize);
-
- /* create M68k message port and startup message */
- if (m68kport = (struct MsgPort *)PPCCreatePort(porttags)) {
- sigppc = 1 << m68kport->mp_SigBit;
-
- if (startupmsg =
- PPCCreateMessage(m68kport,sizeof(struct StartupData))) {
- sd->M68kPort = m68kport;
-
- /* start PowerPC task */
- tasktags[0].ti_Data = (ULONG)taskname; /* task name */
- tasktags[1].ti_Data = (ULONG)args; /* arg1 - cmdline */
- tasktags[3].ti_Data = (ULONG)startupmsg;
- tasktags[4].ti_Data = (ULONG)sd;
- tasktags[5].ti_Data = sizeof(struct StartupData);
- tasktags[6].ti_Data = MSGID_EXIT;
- /* determine stack size for PowerPC */
- pr = (struct Process *)FindTask(NULL);
- if (pr->pr_Task.tc_Node.ln_Type == NT_PROCESS && pr->pr_CLI)
- tasktags[7].ti_Data = *(ULONG *)pr->pr_ReturnAddr;
- else
- tasktags[7].ti_Data = (ULONG)((char *)pr->pr_Task.tc_SPUpper
- - (char *)pr->pr_Task.tc_SPLower);
- CacheClearU();
- if (ppctask = PPCCreateTask(elfobject,tasktags)) {
-
- for (;;) {
- ULONG mid;
- BOOL quit;
- struct StartupData *ppcsd;
-
- sigmask = Wait(sigppc |
- SIGBREAKF_CTRL_C |
- SIGBREAKF_CTRL_D);
-
- /* Message from PPC task */
- if (sigmask & sigppc) {
- quit = FALSE;
- while (ppcmsg = PPCGetMessage(m68kport)) {
- if (mid = PPCGetMessageAttr(ppcmsg,PPCMSGTAG_MSGID)
- == MSGID_EXIT) {
- ppcsd = (struct StartupData *)
- PPCGetMessageAttr(ppcmsg,PPCMSGTAG_DATA);
- rc = ppcsd->retCode; /* set return code */
- quit = TRUE;
- break;
- }
- else { /* received unknown message from PPC task */
- Printf("PPC task sent unknown message "
- "with id = %ld.\n",mid);
- PPCReplyMessage(ppcmsg);
- }
- }
- if (quit) /* PPC task has finished */
- break;
- }
-
- /* CTRL-D immediately kills the PPC task */
- if (sigmask & SIGBREAKF_CTRL_D) {
- PPCDeleteTask(ppctask);
- break;
- }
-
- /* CTRL-C is passed on to the PPC task */
- if (sigmask & SIGBREAKF_CTRL_C) {
- SetSignal(0,SIGBREAKF_CTRL_C);
- PPCSignalTask(ppctask,SIGBREAKF_CTRL_C);
- }
- }
-
- }
- else
- Printf("Unable to create PPC task.\n");
- PPCDeleteMessage(startupmsg);
- }
- else
- Printf("Can't create startup message for PPC task.\n");
- PPCDeletePort(m68kport);
- }
- else
- Printf("Can't create MsgPort for PPC-messages.\n");
- PPCFreeVec(args);
- FreeVec(taskname);
- PPCUnLoadObject(elfobject);
- }
- else
- Printf("%s: Unknown command.\n",elfname);
- }
- else
- Printf("Missing argument <ELF object>!\n");
- if (errfh)
- Close(errfh);
- PPCFreeVec(sd);
- }
- else
- Printf("Not enough memory for startup data.\n");
- CloseLibrary(PPCLibBase);
- }
- else
- Printf("Can't open %s V%ld.\n",ppclibname,PPCLIBVER);
- }
- CloseLibrary((struct Library *)DOSBase);
- exit(rc);
- }
-